/*
输入某二叉树的前序遍历和中序遍历的结果，请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如，给出

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树：

    3
   / \
  9  20
    /  \
   15   7

来源：力扣（LeetCode）
链接：https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
*/


/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */

/*
class Solution {

HashMap<int,int> map = new HashMap<>();
int[] preorder;

public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        this.preorder = preorder;
        for(int i = 0; i < inorder.length; i++) map.put(inorder[i],i);
        return recur(0,0,inorder.length-1);
    }
private:
    TreeNode recur(int pre_root, int in_left, int in_right){
        if(in_left > in_right) return null;
        TreeNode root = new TreeNode(preorder[pre_root]);
        int index = map.get(preorder[pre_root]);
        root.left = recur(pre_root+1,in_left,index-1);
        root.right = recur(pre_root+(index-in_left)+1,index+1,in_right);
        return root;
    }
};

*/

class Solution {
private:
    unordered_map<int, int> index;
public:
    TreeNode* myBuildTree(const vector<int>& preorder, const vector<int>& inorder,
                             int preorder_left, int preorder_right,
                              int inorder_left, int inorder_right){
        //他这个将先序和中序的数列，还有范围都作为参数
        if (preorder_left > preorder_right) {
            return nullptr;
        }
        int preorder_root = preorder_left;//先序的第一位为根，就是索引开始是0
        int inorder_root = index[preorder[preorder_root]];//中序根节点的索引
        //这个root要注意是指针，
        TreeNode* root = new TreeNode(preorder[preorder_root]);//TreeNode类类型变量的指针root
        int size_left_subtree = inorder_root - inorder_left;//左子树长度
        //求根节点的左右子节点
        root->left = myBuildTree(preorder, inorder, 
                                preorder_left + 1, preorder_left + size_left_subtree,
                                inorder_left, inorder_root - 1);
        root->right = myBuildTree(preorder, inorder, 
                                preorder_left + size_left_subtree + 1, 
                                preorder_right, inorder_root + 1, inorder_right);
        return root;
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n = preorder.size();
        for (int i = 0; i < n; ++i) {
            index[inorder[i]] = i;
        }
        return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);
    }
};

/*
1 忘了root是指针类型
2 忘了设置递归结束条件
3 unordered_map的声明放在外面，因为两个类都用到
4 忘记用const来限定vector了
*/


class Solution{
private:
    unordered_map<int,int> index;
public:
    TreeNode* recur(const vector<int>& preorder,const vector<int>& inorder,int pre_left, int pre_right,int in_left,  int in_right){
        if(pre_left > pre_right){return nullptr;}
        int pre_root = pre_left;
        int in_root = index[preorder[pre_root]];
        int left_sub_size = in_root - pre_root;
        TreeNode* root = new TreeNode(preorder[pre_root]);
        root->left = recur(preorder,inorder,pre_left+1,pre_left+left_sub_size, in_left,in_root-1);
        root->right = recur(preorder,inorder,pre_left+left_sub_size+1,pre_right, in_root+1,in_right);
        return root;
    }

    TreeNode* buildTree(std::vector<int>& preorder, std::vector<int>& inorder){
        int n = inorder.size();
        for(int i = 0; i < n; ++i){index[inorder[i]] = i;}
        return recur(preorder,inorder,0,n-1,0,n-1);
    }

};

//修改之后感觉和答案没啥区别了，不知道为啥还是报错，无限递归，可是我补上了终止条件啊



